package org.linlinjava.litemall.wx.controller;

import com.mysql.jdbc.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.ResponseUtil.Response;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.annotation.LogAnno;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.service.WxGoodsService;
import org.linlinjava.litemall.wx.service.WxGoodsSpecificationService;
import org.linlinjava.litemall.wx.vo.AccessoryGroupVo;
import org.linlinjava.litemall.wx.vo.AccessoryVo;
import org.linlinjava.litemall.wx.vo.GoodsVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * wx商品控制器
 * 商品服务
 *
 * @author yliyun
 * @date 2022/09/14
 */
@Api(value="商品controller",tags={"商品操作接口"})
@RestController
@RequestMapping("/wx/goods")
@Validated
public class WxGoodsController {

    /**
     * 商品服务
     */
    @Autowired
	private LitemallGoodsService goodsService;

    /**
     * 收集服务
     */
    @Autowired
	private LitemallCollectService collectService;

    /**
     * 足迹服务
     */
    @Autowired
	private LitemallFootprintService footprintService;

    /**
     * 目录服务
     */
    @Autowired
	private LitemallCategoryService categoryService;

    /**
     * 搜索历史记录服务
     */
    @Autowired
	private LitemallSearchHistoryService searchHistoryService;


    /**
     * 浏览记录服务
     */
    @Autowired
	private LitemallBrowseRecordService browseRecordService;

    /**
     * litemall商品配件服务
     */
    @Autowired
	private LitemallGoodsAccessoryService litemallGoodsAccessoryService;
    /**
     * litemall商店商品服务
     */
    @Autowired
	private LitemallShopMerchandiseService litemallShopMerchandiseService;
    /**
     * litemall商品服务
     */
    @Autowired
	private LitemallMerchandiseService litemallMerchandiseService;
    /**
     * litemall收集配件服务
     */
    @Autowired
	private LitemallCollectAccessoryService litemallCollectAccessoryService;
    /**
     * wx商品服务
     */
    @Autowired
	private WxGoodsService wxGoodsService;

    /**
     * 商品地区服务
     */
    @Autowired
	private LitemallGoodsRegionService goodsRegionService;

    /**
     * 店地区服务
     */
    @Autowired
	private LitemallShopRegionService shopRegionService;

    /**
     * 工作队列
     */
    private final static ArrayBlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<>(9);

    /**
     * 处理程序
     */
    private final static RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    /**
     * 遗嘱执行人服务
     */
    private static ThreadPoolExecutor executorService = new ThreadPoolExecutor(16, 16, 1000, TimeUnit.MILLISECONDS, WORK_QUEUE, HANDLER);

    /**
     * 商品详情
     * <p>
     * 用户可以不登录。
     * 如果用户登录，则记录用户足迹以及返回用户收藏信息。
     *
     * @param userId 用户ID
     * @param id     商品ID
     * @param shopId 商店id
     * @return 商品详情
     */
    @ApiOperation(value="商品详情")
	@GetMapping("detail")
	@LogAnno
	public Response detail(@LoginUser Integer userId, @NotNull Integer id, @NotNull Integer shopId) {
		// 记录用户的足迹 异步处理
		if (userId != null) {
			executorService.execute(()->{
				LitemallFootprint footprint = new LitemallFootprint();
				footprint.setUserId(userId);
				footprint.setGoodsId(id);
				footprintService.add(footprint);
			});
		}
		// 记录用户浏览记录
		executorService.execute(()->{
			LitemallBrowseRecord record = new LitemallBrowseRecord();
			record.setBrowseUserId(userId);
			record.setGoodsId(id);
			record.setAddTime(LocalDateTime.now());
			record.setBrowseNumber(1);
			record.setShopId(shopId);
			browseRecordService.add(record);
		});
		return wxGoodsService.detail(shopId, id, userId);
	}


	@ApiOperation(value="套餐商品详情")
	@GetMapping("package-detail")
	@LogAnno
	public Response packageDetailInfo( @NotNull Integer id, @NotNull Integer shopId) {
		return wxGoodsService.packageDetailInfo(shopId, id);
	}

	@ApiOperation(value="套餐商品列表")
	@GetMapping("package-list")
	@ApiImplicitParam(name = "shopId",value = "门店")
	@LogAnno
	public Response packageList(@RequestParam("shopId") @NotNull Integer shopId) {
		return wxGoodsService.packageList(shopId);
	}


	/**
	 * 编辑详细信息
	 *
	 * @return {@link Response}
	 */
	@ApiOperation(value="购物车编辑商品详情")
	@GetMapping("editDetail")
	@LogAnno
	public Response editDetail(Integer cartId){
    	return wxGoodsService.editDetail(cartId);
	}

    /**
     * 类别
     * 商品分类类目
     *
     * @param id 分类类目ID
     * @return 商品分类类目
     */
    @GetMapping("category")
	@LogAnno
	public Object category(@NotNull Integer id) {
		LitemallCategory cur = categoryService.findById(id);
		LitemallCategory parent = null;
		List<LitemallCategory> children = null;

		if (cur.getPid() == 0) {
			parent = cur;
			children = categoryService.queryByPid(cur.getId());
			cur = children.size() > 0 ? children.get(0) : cur;
		} else {
			parent = categoryService.findById(cur.getPid());
			children = categoryService.queryByPid(cur.getPid());
		}
		Map<String, Object> data = new HashMap<>();
		data.put("currentCategory", cur);
		data.put("parentCategory", parent);
		data.put("brotherCategory", children);
		return ResponseUtil.ok(data);
	}

    /**
     * 列表
     * 根据条件搜素商品
     * <p>
     * 1. 这里的前五个参数都是可选的，甚至都是空
     * 2. 用户是可选登录，如果登录，则记录用户的搜索关键字
     *
     * @param categoryId 分类类目ID，可选
     * @param brandId    品牌商ID，可选
     * @param keyword    关键字，可选
     * @param isNew      是否新品，可选
     * @param isHot      是否热买，可选
     * @param userId     用户ID
     * @param page       分页页数
     * @param limit      分页大小
     * @param sort       排序方式，支持"add_time", "retail_price"或"name"
     * @param order      排序类型，顺序或者降序
     * @param shopId     商店id
     * @return 根据条件搜素的商品详情
     */
    @GetMapping("list")
	@LogAnno
	public Object list(
		@NotNull Integer shopId,
		Integer categoryId,
		Integer brandId,
		String keyword,
		Boolean isNew,
		Boolean isHot,
		@LoginUser Integer userId,
		@RequestParam(defaultValue = "1") Integer page,
		@RequestParam(defaultValue = "10") Integer limit,
		@Sort(accepts = {"add_time", "retail_price", "name"}) @RequestParam(defaultValue = "add_time") String sort,
		@Order @RequestParam(defaultValue = "desc") String order) {

		//添加到搜索历史
		if (userId != null && !StringUtils.isNullOrEmpty(keyword)) {
			LitemallSearchHistory searchHistoryVo = new LitemallSearchHistory();
			searchHistoryVo.setKeyword(keyword);
			searchHistoryVo.setUserId(userId);
			searchHistoryVo.setFrom("app");
			searchHistoryService.save(searchHistoryVo);
		}

		//查询列表数据
		List<LitemallGoods> goodsList = wxGoodsService.list(shopId, categoryId, brandId, keyword, isHot, isNew, page, limit, sort, order);

		// 过滤门店是否在商品所在的区域
		goodsList = goodsList.stream().filter(goods -> {
			List<LitemallGoodsRegion> goodsRegions =   goodsRegionService.queryByGid(goods.getId());
			List<Integer> cityIds = goodsRegions.stream().map(LitemallGoodsRegion::getCityId).collect(Collectors.toList());
			List<LitemallShopRegion> shopRegions =  shopRegionService.queryByShopIdAndRegionIds(shopId,cityIds);

			if(shopRegions != null && shopRegions.size() > 0){
				return  true;
			}else {
				return false;
			}

		}).collect(Collectors.toList());


		List<GoodsVo> goodsVos = goodsList.stream().map(goods->{
//			List<LitemallGoodsProduct> litemallGoodsProducts = productService.queryByGid(goods.getId());
			GoodsVo vo = new GoodsVo();
			vo.setBrief(goods.getBrief());
			vo.setIsHot(goods.getIsHot());
			vo.setId(goods.getId());
			vo.setName(goods.getName());
			vo.setIsNew(goods.getIsNew());
			vo.setPicUrl(goods.getPicUrl());
			vo.setCategoryId(goods.getCategoryId());
			vo.setRetailPrice(goods.getRetailPrice().setScale(2));
			//税详情
//			vo.setTaxes(litemallTaxService.queryByGoodsId(goods.getId()));

			// 用户收藏
			int userHasCollect = 0;
			if (userId != null) {
				userHasCollect = collectService.count(userId, goods.getId());
				vo.setUserHasCollect(userHasCollect > 0);
			}else{
				vo.setUserHasCollect(false);
			}
			LitemallCategory byId = categoryService.findById(goods.getCategoryId());
			if(byId != null){
				vo.setCategoryName(byId.getName());
			}

//			if(litemallGoodsProducts.size() > 0){
//				vo.setRetailPrice(litemallGoodsProducts.get(0).getSellPrice());
//			}
			return vo;
		}).collect(Collectors.toList());

		// 记录用户浏览记录
		if(categoryId != null){
			executorService.execute(()->{
				LitemallBrowseRecord record = new LitemallBrowseRecord();
				record.setBrowseUserId(userId);
				record.setCategoryId(categoryId);
				record.setAddTime(LocalDateTime.now());
				record.setBrowseNumber(1);
				record.setShopId(shopId);
				browseRecordService.add(record);
			});
		}

		// 查询商品所属类目列表。
		List<Integer> goodsCatIds = goodsService.getCatIds(brandId, keyword, isHot, isNew);
		List<LitemallCategory> categoryList = null;
		if (goodsCatIds.size() != 0) {
			categoryList = categoryService.queryL2ByIds(goodsCatIds);
		} else {
			categoryList = new ArrayList<>(0);
		}

		//PageInfo<LitemallGoods> pagedList = PageInfo.of(goodsList);

		Map<String, Object> entity = new HashMap<>();
		/*entity.put("list", goodsVos);
		entity.put("total", pagedList.getTotal());
		entity.put("page", pagedList.getPageNum());
		entity.put("limit", pagedList.getPageSize());
		entity.put("pages", pagedList.getPages());*/
//		entity.put("filterCategoryList", categoryList);

		// 因为这里需要返回额外的filterCategoryList参数，因此不能方便使用ResponseUtil.okList
		return ResponseUtil.ok(entity);
	}

    /**
     * 相关
     * 商品详情页面“大家都在看”推荐商品
     *
     * @param id id
     * @return 商品详情页面推荐商品
     */
    @GetMapping("related")
	@LogAnno
	public Object related(@NotNull Integer id) {
		LitemallGoods goods = goodsService.findById(id);
		if (goods == null) {
			return ResponseUtil.badArgumentValue();
		}

		// 目前的商品推荐算法仅仅是推荐同类目的其他商品
		int cid = goods.getCategoryId();

		// 查找六个相关商品
		int related = 6;
		List<LitemallGoods> goodsList = goodsService.queryByCategory(cid, 0, related);
		return ResponseUtil.okList(goodsList);
	}

    /**
     * 数
     * 在售的商品总数
     *
     * @param shopId 商店id
     * @return 在售的商品总数
     */
    @GetMapping("count")
	@LogAnno
	public Object count(@NotNull Integer shopId) {
		Integer goodsCount = goodsService.queryOnSaleByShop(shopId);
		return ResponseUtil.ok(goodsCount);
	}

    /**
     * 附件
     * 获取商品辅料
     *
     * @param userId  用户id
     * @param goodsId 商品id
     * @param shopId  商店id
     * @return {@link Object}
     */
    @GetMapping("accessory")
	@LogAnno
	public Object accessory(@LoginUser Integer userId, @NotNull Integer goodsId, @NotNull Integer shopId){
		List<LitemallGoodsAccessory> accessories = litemallGoodsAccessoryService.queryByGoodsId(goodsId);

		/**
		 * 判断是否收藏
		 */
		LitemallCollect litemallCollect = null;
		if(userId != null){
			litemallCollect = collectService.queryByGoodsId(userId, goodsId);
		}
		List<LitemallCollectAccessory> litemallCollectAccessories = new ArrayList<>();
		if(litemallCollect != null){
			litemallCollectAccessories.addAll(litemallCollectAccessoryService.queryByCollectId(litemallCollect.getId()));
		}

		List<AccessoryVo> collect = accessories.stream().map(accessory -> {
			AccessoryVo vo = new AccessoryVo();
			BeanUtils.copyProperties(accessory, vo);
			LitemallMerchandise mer = litemallMerchandiseService.findById(accessory.getMerchandiseId());
			if (mer != null) {
				LitemallShopMerchandise shopMerchandise = litemallShopMerchandiseService.queryByMerIdAndShopId(mer.getId(), shopId);
				vo.setUnit(mer.getUnit());

				/**
				 * 设置默认选中数量
				 */
				vo.setSelectNum(0);
				if(litemallCollectAccessories.size() > 0){
					LitemallCollectAccessory findObj = litemallCollectAccessories.stream().filter(item -> {
						return item.getAccessoryId().equals(accessory.getId());
					}).findFirst().orElse(null);
					if(findObj != null){
						vo.setSelectNum(findObj.getNumber());
					}
				}
				if (shopMerchandise != null) {
					vo.setNumber(shopMerchandise.getNumber());
				} else {
					vo.setNumber(0.00);
				}
			}
			return vo;
		}).collect(Collectors.toList());

		List<AccessoryGroupVo> rtn = new ArrayList<>();
		collect.stream().collect(Collectors.groupingBy(AccessoryVo::getGroupName)).forEach((k,v)->{
			AccessoryGroupVo vo = new AccessoryGroupVo();
			vo.setName(k);
			vo.setAccessoryVos(v);
			rtn.add(vo);
		});
		return ResponseUtil.ok(rtn);
	}

	@ApiOperation(value="一级菜单")
    @GetMapping("getCateL1")
	@LogAnno
	public Object getCateL1(){
         return  ResponseUtil.okList(wxGoodsService.getCateL1());
	}

	@ApiOperation(value="二级菜单")
    @GetMapping("getCateL2")
	@LogAnno
	public Object getCateL2(@NotNull Integer id){
		return  ResponseUtil.okList(wxGoodsService.getCateL2(id));
	}

	@ApiOperation(value="三级菜单")
    @GetMapping("getCateL3")
	@LogAnno
	public Response getCateL3(@NotNull  @RequestParam("id") Integer id,Integer shopId){
		return  wxGoodsService.getCateL3(id,shopId);
	}
}
